;
(function (window, angular) {
    'use strict';
    angular.module("Directive.All", ["Directive.Selector", "Directive.Validation"])
        // 控件、元素
        .directive('ybCheckBox', ["$timeout", function ($timeout) {
            return {
                restrict: 'A',
                templateUrl: 'js/directive/tpl/checkTemplate.html',
                replace: true,
                scope: {
                    ybChecked: '=',
                    ybClick: '&',
                    ybDisabled: '=',
                    ybCheckName: '@'
                },
                link: function (scope, element, attrs) {
                    if (angular.isUndefined(scope.ybChecked)) {
                        scope.ybChecked = false;
                    }
                    scope.toggleIcon = function () {
                        if (scope.ybDisabled == true) {
                            return;
                        }
                        if (scope.ybChecked == "notAll") {
                            scope.ybChecked = true;
                        } else {
                            scope.ybChecked = !scope.ybChecked;
                        }
                        $timeout(function () {
                            scope.ybClick();
                        });
                    };
                }
            }
        }])

        .directive('ybRadio', ["$timeout", function ($timeout) {
            return {
                require: '?ngModel',
                restrict: 'A',
                replace: true,
                scope: {
                    ybValue: '=',
                    ybClick: '&',
                    ybRadioName: '@',
                    ybDisabled: "=ybDisabled"
                },
                templateUrl: 'js/directive/tpl/radioTemplate.html',
                link: function (scope, element, attrs, ctrl) {
                    var value = scope.$eval(attrs.value);
                    scope.radioValue = "";
                    if (angular.isObject(value)) {
                        scope.valueIsObj = true;
                    } else {
                        scope.valueIsObj = false;
                    }
                    if (angular.isDefined(value)) {
                        scope.radioValue = value;
                    }
                    if (angular.isDefined(scope.ybValue)) {
                        scope.radioValue = scope.ybValue.id;
                    }

                    scope.changeIcon = function () {
                        if (!!scope.ybDisabled) {
                            return;
                        }
                        ctrl.$setViewValue(scope.radioValue);

                        $timeout(function () {
                            scope.ybClick();
                        });
                    };

                    scope.$watch(function () {
                        return ctrl.$modelValue;
                    }, function () {
                        scope.modelValue = ctrl.$modelValue;
                    });
                }
            }
        }])

        .directive("ybCrumbs", ['$rootScope', '$state', 'EventBus', function ($rootScope, $state, EventBus) {
            return {
                restrict: "A",
                replace: "true",
                scope: {
                    isEdit: '='
                },
                template: "<span>" +
                "<i class='yb-icon ico-address m-r-xs font-12'></i>{{crumbs}}" +
                "</span>",
                link: function (scope, element, attrs, ctrl) {
                    scope.crumbs = "";
                    var curStateName = $state.current.name;
                    var menuItem = $rootScope.primaryMenuItem;

                    function setCrumbs() {
                        if (!menuItem) {
                            return;
                        }
                        scope.crumbs = menuItem.name;
                        angular.forEach(menuItem.children, function (item) {
                            if (item.leaf === 1 && item.state === curStateName) {
                                scope.crumbs += " > " + item.name;
                                return false;
                            }
                            if (item.leaf === 0) {
                                angular.forEach(item.children, function (subItem) {
                                    if (subItem.state === curStateName) {
                                        scope.crumbs += " > " + item.name + " > " + (scope.isEdit ? subItem.name.replace('新增', '编辑') : subItem.name);
                                        return false;
                                    }
                                });
                            }
                        });
                    }

                    EventBus.Subscribe("setCrumbsItem", setCrumbsItem);

                    function setCrumbsItem(data) {
                        menuItem = data;
                        setCrumbs();
                    }

                    scope.$on("$destroy", function () {
                        EventBus.Unsubscribe("setCrumbsItem", setCrumbsItem);
                    });

                    setCrumbs();
                }
            }
        }])

        .directive("ybPageInfo", function () {
            return {
                restrict: "A",
                replace: true,
                scope: {
                    pageInfo: "=ngModel",
                    ybRefresh: "&"
                },
                templateUrl: "js/directive/tpl/pageInfo.html",
                controller: 'PageInfoCtrl'
            };
        })
        .controller("PageInfoCtrl", ["$scope", "$attrs", function ($scope) {
            $scope.targetPage = "1";
            $scope.maxPages = 5;
            $scope.pageSizeList = [
                {
                    code: 10,
                    name: "10/页"
                },
                {
                    code: 20,
                    name: "20/页"
                },
                {
                    code: 30,
                    name: "30/页"
                },
                {
                    code: 40,
                    name: "40/页"
                },
                {
                    code: 50,
                    name: "50/页"
                }
            ];
            if (angular.isDefined($scope.pageInfo.pageSizeList) && $scope.pageInfo.pageSizeList.length > 0) {
                $scope.pageSizeList = $scope.pageInfo.pageSizeList;
            }
            if (!!$scope.pageInfo && !!$scope.pageInfo.hidePageNo) {
                $scope.maxPages = 0;
            }

            $scope.changePageSize = function () {
                $scope.pageInfo.curPage = 1;
                $scope.ybRefresh();
            };

            $scope.pageChange = function () {
                $scope.ybRefresh();
            };

            $scope.pageJump = function (targetPage) {
                $scope.targetPage = targetPage.replace(/\b(0+)/gi, "");
                var totalPages = $scope.pageInfo.totalPages;
                var regPage = /^\d+$/;
                if ($scope.targetPage < 1 || !regPage.test($scope.targetPage)) {
                    $scope.targetPage = 1;
                }
                if ($scope.targetPage > totalPages) {
                    $scope.targetPage = totalPages;
                }
                $scope.pageInfo.curPage = $scope.targetPage;
                $scope.ybRefresh();
            };
        }])

        .directive('ngScrollbar', [
            function () {
                return {
                    restrict: 'AE',
                    transclude: true,
                    scope: {
                        scrollbarConfig: '=scrollbarConfig',
                        scrollbarX: '@', // the value is true or false, to configure the x scrollbar create or no create.
                        scrollbarY: '@' // the value is true or false, to configure the y scrollbar create or no create.
                    },
                    template: '<div style="position:relative;width:100%;height:100%;">\
                                    <div class="ngscroll-content-container" style="display:inline-block;width:100%;margin-top:0;margin-left:0" ng-transclude>\
                                    </div>\
                                    <ng-scrollbar-x ng-if="scrollbarX || scrollbarX === undefined"></ng-scrollbar-x>\
                                    <ng-scrollbar-y ng-if="scrollbarY || scrollbarY === undefined"></ng-scrollbar-y>\
                                </div>',
                    controller: 'scrollbarController',
                    compile: function (element) {
                        if (window.navigator.userAgent.indexOf("MSIE 8.0") == -1) {
                            element.css('overflow', 'hidden');
                            return function (scope, element, attrs, ctrl) {
                                ctrl.init(element, scope.scrollbarConfig);
                            };
                        } else {
                            element.css('overflow', 'auto');
                            return;
                        }
                    }
                };
            }
        ])
        .controller('scrollbarController', [function () {
            var defaultConfig = {
                dragSpeed: 1, //default browser delta value is 120 or -120
                autoResize: false, // if need auto resize, default false
                show: false, // if need show when mouse not enter the container element which need scrollbar, default false.
                scrollbar: {
                    width: 6, //scrollbar width
                    hoverWidth: 8, //scrollbar width when the mouse hover on it
                    color: 'rgba(0,0,0,1)' //scrollbar background color
                },
                scrollbarContainer: {
                    width: 12, //scrollbarContainer width
                    color: 'rgba(0,0,0,1)' // scrollbarContainer background
                }
            };
            var containerElement, // the element which need the directive of ngscrollbar
                contentElement, // the element which transclude the true content
                config, // config
                scrollbarMargin, // the variable is used to descide the scrollbar element top or left to its parent element scrollbarContainer
                scrollbarHoverMargin; // the variable is used to descide the scrollbar element top or left to its parent element scrollbarContainer when the mouse hover on the scrollbar

            /**
             * it must be called before the controller is used.
             * @param  {jqlite object} element         it's necessary variable
             * @param  {object} scrollbarConfig        the config which is defined by user
             * @return
             */
            this.init = function (element, scrollbarConfig) {
                containerElement = element;
                config = angular.copy(angular.extend(defaultConfig, scrollbarConfig || {}));
                contentElement = angular.element(element[0].querySelector('.ngscroll-content-container'));
                scrollbarMargin = (config.scrollbarContainer.width - config.scrollbar.width) / 2;
                scrollbarHoverMargin = (config.scrollbarContainer.width - config.scrollbar.hoverWidth) / 2;
            };

            angular.extend(this, {
                /**
                 * Wrap window in an angular jqLite object.
                 */
                winEl: angular.element(window),
                /**
                 * get the element which need the directive of ngscrollbar
                 * @return {jqlite object}
                 */
                getContainerElement: function () {
                    return containerElement;
                },
                /**
                 * the element which transclude the true content
                 * @return {jqlite object}
                 */
                getContentElement: function () {
                    return contentElement;
                },
                /**
                 * get the config
                 * @return {object}
                 */
                getConfig: function () {
                    return config;
                },
                /**
                 * get the scrollbarMargin
                 * @return {number}
                 */
                getScrollbarMargin: function () {
                    return scrollbarMargin;
                },
                /**
                 * get the scrollbarHoverMargin
                 * @return {number}
                 */
                getScrollbarHoverMargin: function () {
                    return scrollbarHoverMargin;
                }
            });
        }])
        .directive('ngScrollbarY', ['$timeout', function ($timeout) {
            return {
                restrict: 'AE',
                require: '^ngScrollbar',
                replace: true,
                template: '<div class="ngscrollbar-container-y" ng-style="styles.scrollbarContainer"><div class="ngscrollbar-y" ng-style="styles.scrollbar"></div></div>',
                compile: function () {
                    return function (scope, element, attrs, ctrl) {

                        var config = ctrl.getConfig(),
                            docEl = angular.element(document),
                            containerElement = ctrl.getContainerElement(),
                            contentElement = ctrl.getContentElement(),
                            scrollbar = angular.element(element[0].querySelector('.ngscrollbar-y')),
                            scrollbarMargin = ctrl.getScrollbarMargin(),
                            scrollbarHoverMargin = ctrl.getScrollbarHoverMargin();

                        scope.styles = {
                            scrollbarContainer: {
                                position: 'absolute',
                                width: config.scrollbarContainer.width + 'px',
                                height: '100%',
                                top: 0,
                                right: '-1px',
                                background: config.scrollbarContainer.color,
                                // 'border-radius': config.scrollbarContainer.width / 2 + 'px'
                                'border-radius': '0px'
                            },
                            scrollbar: {
                                position: 'absolute',
                                width: config.scrollbar.width + 'px',
                                right: scrollbarMargin + 'px',
                                cursor: 'default',
                                opacity: 0,
                                transition: 'opacity .3s ease-in-out, border-radius .1s linear, width .1s linear, right .1s linear',
                                background: config.scrollbar.color,
                                'border-radius': config.scrollbar.width / 2 + 'px'
                                // 'border-radius': '0px'
                            }
                        };

                        var getContentHeight = function () {
                            return contentElement[0].offsetHeight;
                        };

                        var getContainerHeight = function () {
                            return containerElement[0].offsetHeight;
                        };

                        var getScrollbarHeight = function () {
                            var height = Math.pow(getContainerHeight(), 2) / getContentHeight() - scrollbarMargin * 2;
                            return height;
                        };

                        var isOverflow = function () {
                            return getContentHeight() > getContainerHeight();
                        };

                        var hideScrollbar = function () {
                            scrollbar.css('opacity', 0);
                        };

                        var showScrollbar = function () {
                            scrollbar.css('opacity', 1);
                        };

                        var reset = function () {
                            var oldMarginTop = parseInt(contentElement.css('margin-top'), 10);
                            contentElement.css('margin-top', '0px'); // this is for the element which has the attribute of max-height
                            if (isOverflow()) {
                                element.css('display', 'block');
                                scrollbar.css('height', getScrollbarHeight() + 'px');
                                scrollTo(oldMarginTop);
                                if (config.show) {
                                    showScrollbar();
                                }
                            } else {
                                element.css('display', 'none');
                            }
                        };

                        var scrollTo = function (top) {
                            top = Math.min(0, Math.max(top, getContainerHeight() - getContentHeight()));
                            contentElement.css('margin-top', top + 'px');
                            scrollbar.css('top', -top / getContentHeight() * getContainerHeight() + scrollbarMargin + 'px');
                        };

                        var scroll = function (distance) {
                            var newTop = parseInt(contentElement.css('margin-top'), 10) + distance;
                            scrollTo(newTop);
                        };

                        containerElement.on('mousewheel', function (event) {
                            if (!isOverflow()) {
                                return;
                            }
                            event.preventDefault();
                            if (event.originalEvent !== undefined) {
                                event = event.originalEvent;
                            }
                            scroll(event.wheelDeltaY || event.wheelDelta);
                        });

                        if (window.navigator.userAgent.toLowerCase().indexOf('firefox') >= 0) {
                            containerElement.on('wheel', function (event) {
                                if (!isOverflow()) {
                                    return;
                                }
                                event.preventDefault();
                                if (event.originalEvent !== undefined) {
                                    event = event.originalEvent;
                                }
                                scroll(-event.deltaY * 40);// the ff delta value is 3 or -3 when scroll and the chrome or ie is -120 or 120, so it must multiply by 40
                            });
                        }

                        element.on('mouseenter', function () {
                            // element.css('background', config.scrollbarContainer.color);
                            scrollbar.css('width', config.scrollbar.hoverWidth + 'px');
                            scrollbar.css('right', scrollbarHoverMargin + 'px');
                            // scrollbar.css('border-radius', config.scrollbar.hoverWidth / 2 + 'px');
                        });

                        element.on('mouseleave', function () {
                            // element.css('background', 'none');
                            scrollbar.css('width', config.scrollbar.width + 'px');
                            scrollbar.css('right', scrollbarMargin + 'px');
                            // scrollbar.css('border-radius', config.scrollbar.width / 2 + 'px');
                        });

                        var scrollbarMousedown = false,
                            axisY,
                            mouseInElement = false;

                        if (!config.show) {
                            containerElement.on('mouseenter', function () {
                                mouseInElement = true;
                                showScrollbar();
                            });
                            containerElement.on('mouseleave', function () {
                                mouseInElement = false;
                                if (scrollbarMousedown) {
                                    return;
                                }
                                hideScrollbar();
                            });
                        }

                        scrollbar.on('mousedown', function (event) {
                            event.preventDefault();
                            axisY = event.screenY;
                            scrollbarMousedown = true;
                            docEl.one('mouseup', function () {
                                scrollbarMousedown = false;
                                if (!config.show && !mouseInElement) {
                                    hideScrollbar();
                                }
                                // docEl.off('mouseup', arguments.callee);
                            });
                        });
                        docEl.on('mousemove', function (event) {
                            if (scrollbarMousedown) {
                                event.preventDefault();
                                scroll(-(event.screenY - axisY) * config.dragSpeed * getContentHeight() / getContainerHeight());
                                axisY = event.screenY;
                            }
                        });

                        $timeout(function () {
                            reset();
                            if (!!document.createStyleSheet) { //if the browser is ie browser
                                contentElement.on('DOMNodeInserted', reset);
                                contentElement.on('DOMNodeRemoved', reset);
                            } else {
                                var observer = new MutationObserver(function (mutations) {
                                    if (mutations.length) {
                                        reset();
                                    }
                                });
                                observer.observe(contentElement[0], {childList: true, subtree: true});
                            }
                        }, 5);

                        // Redraw the scrollbar when window size changes.
                        if (config.autoResize) {
                            // Closure to guard against leaking variables.
                            (function () {
                                var redrawTimer;

                                ctrl.winEl.on('resize', function (e) {
                                    if (redrawTimer) {
                                        clearTimeout(redrawTimer);
                                    }
                                    redrawTimer = setTimeout(function () {
                                        redrawTimer = null;
                                        reset();
                                    }, 50);
                                });
                            })();
                        }
                    };
                }
            };
        }])
        .directive('ngScrollbarX', ['$timeout', function ($timeout) {
            return {
                restrict: 'AE',
                replace: true,
                require: '^ngScrollbar',
                template: '<div class="ngscrollbar-container-x" ng-style="styles.scrollbarContainer"><div class="ngscrollbar-x" ng-style="styles.scrollbar"></div></div>',
                compile: function () {
                    return function (scope, element, attrs, ctrl) {

                        var config = ctrl.getConfig(),
                            docEl = angular.element(document),
                            containerElement = ctrl.getContainerElement(),
                            containerDom = containerElement[0],
                            contentElement = ctrl.getContentElement(), //the container of content
                            scrollbar = angular.element(element[0].querySelector('.ngscrollbar-x')),
                            scrollbarMargin = ctrl.getScrollbarMargin(),
                            scrollbarHoverMargin = ctrl.getScrollbarHoverMargin();

                        scope.styles = {
                            scrollbarContainer: {
                                position: 'absolute',
                                width: '100%',
                                transition: 'background .3s ease-in-out',
                                'border-radius': config.scrollbarContainer.width / 2 + 'px'
                            },
                            scrollbar: {
                                position: 'absolute',
                                cursor: 'default',
                                opacity: 0,
                                transition: 'opacity .3s ease-in-out, border-radius .1s linear, width .1s linear, right .1s linear',
                                background: config.scrollbar.color,
                                'border-radius': config.scrollbar.width / 2 + 'px'
                            }
                        };

                        element.css('height', config.scrollbarContainer.width + 'px'); // set the scrollbarContainer height;
                        element.css('bottom', 0); // set scrollbarContainer top
                        element.css('left', 0); //set scrollbarContainer left
                        scrollbar.css('top', scrollbarMargin + 'px'); //set scrollbar top
                        scrollbar.css('height', config.scrollbar.width + 'px');

                        var getContentWidth = function () {
                            return contentElement[0].scrollWidth;
                        };

                        var getContainerWidth = function () {
                            return containerDom.offsetWidth;
                        };

                        var getScrollbarWidth = function () {
                            return Math.pow(getContainerWidth(), 2) / getContentWidth() - scrollbarMargin * 2;
                        };

                        var showScrollbar = function () {
                            scrollbar.css('opacity', 1);
                        };

                        var hideScrollbar = function () {
                            scrollbar.css('opacity', 0);
                        };

                        var isOverflow = function () {
                            return getContentWidth() > getContainerWidth();
                        };

                        var reset = function () {
                            var oldMarginLeft = parseInt(contentElement.css('margin-left'), 10);
                            contentElement.css('margin-left', '0px');
                            if (isOverflow()) {
                                element.css('display', 'block');
                                scrollbar.css('width', getScrollbarWidth() + 'px');
                                scrollTo(oldMarginLeft);
                                if (config.show) {
                                    showScrollbar();
                                }
                            } else {
                                element.css('display', 'none');
                            }
                        };

                        var scrollTo = function (left) {
                            left = Math.min(0, Math.max(left, getContainerWidth() - getContentWidth()));
                            contentElement.css('margin-left', left + 'px');
                            scrollbar.css('left', -left / getContentWidth() * getContainerWidth() + scrollbarMargin + 'px');
                        };

                        var scroll = function (distance) {
                            var left = parseInt(contentElement.css('margin-left'), 10) + distance;
                            scrollTo(left);
                        };

                        element.on('mouseenter', function () {
                            element.css('background', config.scrollbarContainer.color);
                            scrollbar.css('height', config.scrollbar.hoverWidth + 'px');
                            scrollbar.css('top', scrollbarHoverMargin + 'px');
                            scrollbar.css('border-radius', config.scrollbar.hoverWidth / 2 + 'px');
                        });

                        element.on('mouseleave', function () {
                            element.css('background', 'none');
                            scrollbar.css('height', config.scrollbar.width + 'px');
                            scrollbar.css('top', scrollbarMargin + 'px');
                            scrollbar.css('border-radius', config.scrollbar.width / 2 + 'px');
                        });

                        var scrollbarMousedown = false,
                            axisX,
                            mouseInElement = false;

                        if (!config.show) {
                            containerElement.on('mouseenter', function () {
                                mouseInElement = true;
                                showScrollbar();
                            });
                            containerElement.on('mouseleave', function () {
                                mouseInElement = false;
                                if (scrollbarMousedown) {
                                    return;
                                }
                                hideScrollbar();
                            });
                        }

                        scrollbar.on('mousedown', function (event) {
                            event.preventDefault();
                            scrollbarMousedown = true;
                            axisX = event.screenX;
                            docEl.one('mouseup', function () {
                                scrollbarMousedown = false;
                                if (!config.show && !mouseInElement) {
                                    hideScrollbar();
                                }
                                // docEl.off('mouseup', arguments.callee);
                            });
                        });
                        docEl.on('mousemove', function (event) {
                            if (scrollbarMousedown) {
                                event.preventDefault();
                                scroll(-(event.screenX - axisX) * config.dragSpeed * getContentWidth() / getContainerWidth());
                                axisX = event.screenX;
                            }
                        });

                        $timeout(function () {
                            reset();
                            if (!!document.createStyleSheet) { //if the browser is ie browser
                                contentElement.on('DOMNodeInserted', reset);
                                contentElement.on('DOMNodeRemoved', reset);
                            } else {
                                var observer = new MutationObserver(function (mutations) {
                                    if (mutations.length) {
                                        reset();
                                    }
                                });
                                observer.observe(contentElement[0], {childList: true, subtree: true});
                            }
                        }, 5);

                        // Redraw the scrollbar when window size changes.
                        if (config.autoResize) {
                            // Closure to guard against leaking variables.
                            (function () {
                                var redrawTimer;

                                ctrl.winEl.on('resize', function (e) {
                                    if (redrawTimer) {
                                        clearTimeout(redrawTimer);
                                    }
                                    redrawTimer = setTimeout(function () {
                                        redrawTimer = null;
                                        reset();
                                    }, 50);
                                });
                            })();
                        }
                    };
                }
            };
        }])

        .directive('ybStepBar', ["$timeout", function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    stepData: '=?ngModel'
                },
                templateUrl: 'js/directive/tpl/stepBar.html',
                link: function (scope, element, attrs, ctrl) {
                    scope.stepWidth = {width: 100 / (scope.stepData.list.length - 1) + "%"};
                }
            }
        }])

        .directive('ybShuttleBox', ["$timeout", function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    shuttleConf: '=?ngModel',
                    leftTbConf: "=",
                    rightTbConf: "="
                },
                templateUrl: 'js/directive/tpl/shuttleBox.html',
                controller: 'ShuttleBoxCtrl'
            }
        }])
        .controller('ShuttleBoxCtrl', ["$scope", "ybWidget", "ybHttp", function ($scope, ybWidget, ybHttp) {
            $scope.markInfo = {allChecked: false};
            $scope.pageInfo = {
                totalPages: 1,
                totalRows: 0,
                pageSize: 10,
                curPage: 1
            };
            $scope.leftDataConf = $scope.shuttleConf.leftDataConf;
            $scope.condition = {};
            $scope.condition[$scope.shuttleConf.leftDataConf.condition.key] = "";
            $scope.leftData = [];
            $scope.rightData = $scope.shuttleConf.rightData;

            function getLeftData(curPage) {
                $scope.leftData = [
                    {
                        dealerOrgId: "135406368042516480",
                        companyName: "asdasd"
                    },
                    {
                        dealerOrgId: "135406368042516481",
                        companyName: "asdasd"
                    },
                    {
                        dealerOrgId: "135406368042516482",
                        companyName: "asdasd"
                    }
                ];
                angular.forEach($scope.leftData, function (item) {
                    item.isChecked = false;
                });
                setDataChecked();
                return;
                var service = $scope.leftDataConf.service;
                var reqUrl = $scope.leftDataConf.reqUrl;
                var param = {};
                if (!!$scope.leftDataConf.page) {
                    param.pageSize = $scope.pageInfo.pageSize;
                    if (!!curPage) {
                        $scope.pageInfo.curPage = curPage;
                    }
                    param.pageNum = $scope.pageInfo.curPage;
                }
                param.filters = angular.copy($scope.condition);
                ybHttp[$scope.leftDataConf.reqType](service, reqUrl, param).then(function (resp) {
                    if (resp.code !== 0) {
                        ybWidget.ShowMessage(resp, MESG_TYPE.Error);
                        return;
                    }
                    angular.forEach(resp.value.list, function (item) {
                        item.isChecked = false;
                    });
                    if (!!$scope.leftDataConf.page) {
                        $scope.pageInfo.totalRows = resp.value.total;
                        $scope.pageInfo.totalPages = resp.value.pages;
                    }
                    $scope.leftData = resp.value.list;
                    setDataChecked();
                });
            }

            $scope.search = function () {
                getLeftData();
            };

            $scope.selectAll = function () {
                for (var i = 0, len = $scope.leftData.length; i < len; i++) {
                    $scope.leftData[i].isChecked = $scope.markInfo.allChecked;
                }
                selectData();
            };

            function checkAll() {
                var selectAll = false;
                for (var i = 0, len = $scope.leftData.length; i < len; i++) {
                    if (!$scope.leftData[i].isChecked) {
                        selectAll = false;
                        break;
                    }
                    selectAll = true;
                }
                return selectAll;
            }

            $scope.selectSingle = function (item) {
                var selectAll = false;
                if (!item.isChecked) {
                    selectAll = false;
                } else {
                    if (!checkAll()) {
                        selectAll = false;
                    } else {
                        selectAll = true;
                    }
                }
                $scope.markInfo.allChecked = selectAll;
                selectData(item);
            };

            function setDataChecked(item) {
                if (angular.isDefined(item)) {
                    for (var i = 0, len = $scope.leftData.length; i < len; i++) {
                        if ($scope.leftData[i][$scope.shuttleConf.checkFiled] === item[$scope.shuttleConf.checkFiled]) {
                            $scope.leftData[i].isChecked = false;
                            break;
                        }
                    }
                } else {
                    for (var i = 0, len = $scope.leftData.length; i < len; i++) {
                        if ($scope.rightData.length === 0) {
                            $scope.leftData[i].isChecked = false
                        }
                        for (var j = 0, lenJ = $scope.rightData.length; j < lenJ; j++) {
                            if ($scope.leftData[i][$scope.shuttleConf.checkFiled] === $scope.rightData[j][$scope.shuttleConf.checkFiled]) {
                                $scope.leftData[i].isChecked = true;
                                break;
                            }
                        }
                    }
                }
                $scope.markInfo.allChecked = checkAll();
            }

            function selectData(item) {
                if (angular.isDefined(item)) {
                    if (!!item.isChecked) {
                        $scope.rightData.push(item);
                    } else {
                        for (var i = 0, len = $scope.rightData.length; i < len; i++) {
                            if ($scope.rightData[i][$scope.shuttleConf.checkFiled] === item[$scope.shuttleConf.checkFiled]) {
                                $scope.rightData.splice(i, 1);
                                break;
                            }
                        }
                    }
                } else {
                    if (!!$scope.markInfo.allCheckedClient && $scope.rightData.length === 0) {
                        $scope.rightData = angular.copy($scope.leftData);
                        return
                    }
                    for (var i = 0, len = $scope.leftData.length; i < len; i++) {
                        var existed = false;
                        if (!!$scope.leftData[i].isChecked) {
                            for (var j = 0, lenJ = $scope.rightData.length; j < lenJ; j++) {
                                if ($scope.rightData[j][$scope.shuttleConf.checkFiled] === $scope.leftData[i][$scope.shuttleConf.checkFiled]) {
                                    existed = true;
                                    break;
                                }
                            }
                            if (!existed) {
                                $scope.rightData.push($scope.leftData[i]);
                            }
                        } else {
                            for (var j = $scope.rightData.length - 1; j >= 0; j--) {
                                if ($scope.rightData[j][$scope.reqParams.checkFiled] === $scope.leftData[i][$scope.reqParams.checkFiled]) {
                                    $scope.rightData.splice(j, 1);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            $scope.removeClient = function (item, index) {
                $scope.rightData.splice(index, 1);
                setDataChecked(item);
            };

            $scope.clearRight = function () {
                $scope.rightData = [];
                setDataChecked();
            };

            (function () {
                getLeftData(1);
            })();
        }])

        .directive('ybTimeLine', ["$timeout", function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    dataModel: '=?ngModel',
                    canEnter: "=",
                    timeFrameNew: "=",
                    enterFunc: "&"
                },
                templateUrl: 'js/directive/tpl/timeLine.html',
                controller: 'TimeLineCtrl'
            }
        }])
        .controller('TimeLineCtrl', ["$scope", "ybWidget", "ybHttp", "$filter", "EventBus", function ($scope, ybWidget, ybHttp, $filter, EventBus) {
            $scope.showCurTime = true;
            $scope.formShow = false;
            $scope.curTime = new Date().getTime();
            function setTimeShow() {
                var lastDataDate = new Date($scope.dataModel[$scope.dataModel.length - 1].date).getTime();
                if ($filter("YbDate")($scope.curTime) === $filter("YbDate")(lastDataDate)) {
                    $scope.showCurTime = false;
                }
            }
            setTimeShow();

            $scope.switchForm = function () {
                $scope.formShow = !$scope.formShow;
            };

            $scope.submit = function () {
                $scope.timeFrameNew.date = $scope.curTime;
                $scope.enterFunc();
            };

            EventBus.Subscribe("entryTimeFrame", entryTimeFrame);

            function entryTimeFrame() {
                $scope.timeFrameNew.msg = "";
                $scope.formShow = false;
                $scope.curTime = new Date().getTime();
                setTimeShow();
            }

            $scope.$on("$destroy", function () {
                EventBus.Unsubscribe("entryTimeFrame", entryTimeFrame);
            });

        }])

        //工具栏类
        .directive("ybAdvanceSearch", ['$document', function ($document) {
            return {
                restrict: "A",
                replace: "true",
                scope: {
                    showToolbar: '=',
                    searchData: "&",
                    resetData: "&"
                },
                transclude: true,
                templateUrl: "js/directive/tpl/advanceSearch.html",
                link: function (scope, element, attrs, ctrl) {

                    function closePopup() {
                        scope.showToolbar = false;
                    }

                    scope.cancel = function () {
                        closePopup()
                    };

                    $document.on('click', function () {
                        if (!!scope.showToolbar) {
                            scope.$apply(function () {
                                closePopup();
                            });
                        }
                    });
                }
            }
        }])

        // 表格操作类
        .directive("ybColConfig", ["$document", "$timeout", function ($document, $timeout) {
            return {
                restrict: "EA",
                replace: "true",
                scope: {
                    showToolbar: '=',
                    dataModel: "=?ngModel",            // 绑定数据模型
                    colFixed: "=",                     // 包含固定列
                    fixedWidth: "=",                   // 固定列的宽
                    scrollWidth: "=",                  // 滚动列的宽
                    hasCheckCol: "@",                  // 是否有选择列
                    setTbStyle: "&"
                },
                templateUrl: "js/directive/tpl/colConfig.html",
                link: function (scope) {
                    var watcher = scope.$watch("showToolbar", function (value, oldValue) {
                        if (!!value) {
                            scope.configList = angular.copy(scope.dataModel.tableCol);
                        }
                    });

                    scope.$on('$destroy', function () {
                        watcher();
                        watcher = null;
                    });

                    scope.setCol = function (close) {
                        scope.dataModel.tableCol = angular.copy(scope.configList);
                        setTabWidth();
                        if (!!close) {
                            closePopup();
                        }
                    };

                    function setTabWidth() {
                        var fixedWidth = 0;
                        var scrollWidth = 0;
                        if (!!scope.hasCheckCol && !!scope.colFixed) {
                            fixedWidth = 40;
                        }
                        for (var i = 0, len = scope.dataModel.tableCol.length; i < len; i++) {
                            if (!!scope.dataModel.tableCol[i].isShow && !!scope.dataModel.tableCol[i].isFixed) {
                                fixedWidth += scope.dataModel.tableCol[i].width;
                            }
                            if (!!scope.dataModel.tableCol[i].isShow && !scope.dataModel.tableCol[i].isFixed) {
                                scrollWidth += scope.dataModel.tableCol[i].width;
                            }
                        }
                        scope.dataModel.fixedWidth = fixedWidth;
                        scope.dataModel.scrollWidth = scrollWidth;
                        $timeout(function () {
                            scope.setTbStyle();
                        });
                    }

                    scope.cancel = function () {
                        scope.configList = angular.copy(scope.dataModel.tableCol);
                        closePopup();
                    };

                    scope.moveIndex = function (index, type) {
                        var curItem = angular.copy(scope.configList[index]);
                        var targetIndex = 0;
                        if (type === "up") {
                            targetIndex = index - 1;
                        }
                        if (type === "down") {
                            targetIndex = index + 1;
                        }
                        scope.configList[index] = scope.configList[targetIndex];
                        scope.configList[targetIndex] = curItem;
                    };

                    function closePopup() {
                        scope.showToolbar = false;
                    }

                    $document.on('click', function () {
                        if (!!scope.showToolbar) {
                            scope.$apply(function () {
                                closePopup();
                            });
                        }
                    });
                }
            }
        }])

        .directive('ybTableFixed', [function () {
            return {
                restrict: 'AE',
                scope: {
                    eleCount: "@",
                    scrollArea: "@"
                },
                link: function ($scope, element) {
                    var mouseTarget = "";        // 鼠标悬停的目标元素
                    var eleScrollIndexS = 0;     // 上下左右滚动元素的索引 -- 主滚动元素
                    var eleScrollIndexX = 0;     // 跟随左右滚动元素的索引 -- 标题
                    var eleScrollIndexY = 0;     // 跟随上下滚动元素的索引 -- 固定列
                    var menuElement = angular.element(document.getElementById("contextMenu"));
                    if (angular.isUndefined($scope.scrollArea)) {
                        eleScrollIndexS = 1;
                        eleScrollIndexX = 0;
                    } else {
                        if ($scope.scrollArea === "left") {
                            eleScrollIndexS = $scope.eleCount / 2;
                            eleScrollIndexX = 0;
                            eleScrollIndexY = $scope.eleCount - 1;
                        }
                        if ($scope.scrollArea === "right") {
                            eleScrollIndexS = $scope.eleCount - 1;
                            eleScrollIndexX = ($scope.eleCount / 2) - 1;
                            eleScrollIndexY = $scope.eleCount / 2;
                        }
                    }

                    element[0].children[eleScrollIndexY].onmouseover = function () {
                        mouseTarget = "scrollY";
                    };
                    element[0].children[eleScrollIndexY].onmouseout = function () {
                        mouseTarget = "";
                    };
                    element[0].children[eleScrollIndexS].onmouseover = function () {
                        mouseTarget = "scrollS";
                    };
                    element[0].children[eleScrollIndexS].onmouseout = function () {
                        mouseTarget = "";
                    };

                    element[0].children[eleScrollIndexY].onscroll = function () {
                        if (mouseTarget === "scrollY") {
                            var scrollTop = element[0].children[eleScrollIndexY].scrollTop;
                            element[0].children[eleScrollIndexS].scrollTop = scrollTop;
                        }
                    };

                    element[0].children[eleScrollIndexS].onscroll = function () {
                        if (mouseTarget === "scrollS") {
                            var scrollTop = element[0].children[eleScrollIndexS].scrollTop;
                            var scrollLeft = element[0].children[eleScrollIndexS].scrollLeft;
                            if (angular.isDefined($scope.scrollArea)) {
                                element[0].children[eleScrollIndexY].scrollTop = scrollTop;
                            }
                            element[0].children[eleScrollIndexX].scrollLeft = scrollLeft;
                        }
                        if (menuElement.length > 0) {
                            menuElement.css("display", "none");
                        }
                    };
                }
            };
        }])

        .directive('ybThDrag', [function () {
            return {
                restrict: 'A',
                scope: {
                    colWidth: "=",
                    targetWidth: "=",
                    fixedWidth: "="
                },
                link: function (scope, element, attrs, $event) {
                    var tableWidth = 0;
                    var thisWidth = 0;
                    var finalPosition = 0;
                    var tableActualWidth = 0;
                    var moveDistance = 0;       // 鼠标移动的距离
                    element[0].onmousedown = function ($event) {
                        var e = $event || window.event;
                        var disX = e.clientX;
                        tableWidth = parseInt(scope.targetWidth);
                        thisWidth = element.parent()[0].offsetWidth;
                        document.onmousemove = function ($event) {
                            var ev = $event || window.event;
                            moveDistance = ev.clientX - disX;
                            finalPosition = thisWidth + moveDistance;
                            tableActualWidth = tableWidth + moveDistance;
                            if (finalPosition < 80) {
                                return
                            }
                            element.parent()[0].width = finalPosition;
                            scope.$apply(function () {
                                scope.colWidth = finalPosition;
                                scope.targetWidth = tableActualWidth;
                                if (angular.isDefined(scope.fixedWidth)) {
                                    scope.fixedWidth = {left: tableActualWidth + "px"};
                                }
                            });
                        };

                        document.onmouseup = function () {
                            element.releaseCapture && element.releaseCapture();
                            document.onmousemove = null;
                            document.onmouseup = null;
                        };
                    };
                }
            }
        }])

        .directive('ybTheadOperate', [function () {
            return {
                restrict: "EA",
                replace: "true",
                scope: {
                    dataModel: "=?ngModel",
                    colWidth: "=",
                    targetWidth: "=",
                    fixedWidth: "="
                },
                templateUrl: "js/directive/tpl/theadOperate.html",
                link: function (scope, element, attrs, $event) {
                    var tableWidth = 0;
                    var thisWidth = 0;
                    var finalPosition = 0;
                    var tableActualWidth = 0;
                    var moveDistance = 0;       // 鼠标移动的距离
                    var dragEle = element.children().children()[0];
                    dragEle.onmousedown = function ($event) {
                        var e = $event || window.event;
                        var disX = e.clientX;
                        tableWidth = parseInt(scope.targetWidth);
                        thisWidth = element.parent()[0].offsetWidth;
                        document.onmousemove = function ($event) {
                            var ev = $event || window.event;
                            moveDistance = ev.clientX - disX;
                            finalPosition = thisWidth + moveDistance;
                            tableActualWidth = tableWidth + moveDistance;
                            if (finalPosition < 80) {
                                return
                            }
                            element.parent()[0].width = finalPosition;
                            scope.$apply(function () {
                                scope.dataModel.width = finalPosition;
                                scope.targetWidth = tableActualWidth;
                                if (angular.isDefined(scope.fixedWidth)) {
                                    scope.fixedWidth = {left: tableActualWidth + "px"};
                                }
                            });
                        };

                        document.onmouseup = function () {
                            element.releaseCapture && element.releaseCapture();
                            document.onmousemove = null;
                            document.onmouseup = null;
                        };
                    };
                }
            }
        }])

        // 功能类
        .directive("ybDownload", ['$compile', 'ybWidget', 'MESG_TYPE', function ($compile, ybWidget, MESG_TYPE) {
            return {
                restrict: "A",
                replace: "false",
                scope: {
                    downloadUrl: "=",
                    downloadParam: "=",
                    downloadKey: "@"
                },
                link: function (scope, element, attrs) {
                    const downloadUrlNew = scope.downloadUrl.replace('/dev/', '/devrpt/');
                    scope.downloadUrl = `${downloadUrlNew}?SC-AUTH=${localStorage.getItem("ScAuthM")}`;
                    var template = "<div class='hidden'>" +
                        "<form  action='{{downloadUrl}}' method='post' id='myform' target='ybDownloadFileForm'>" +
                        "<div ng-repeat='(key,value) in downloadParam'>" +
                        "<input type='text' name='{{key}}' ng-model='value'/>" +
                        "</div>" +
                        "</form>" +
                        "</div>" +
                        "<iframe name='ybDownloadFileForm' ng-hide='true'></iframe>";
                    var formTemplate = angular.element(template);
                    $compile(formTemplate)(scope);
                    element.after(formTemplate);
                    element.on("click", submitRequest);
                    function submitRequest() {
                        if (angular.isDefined(scope.downloadKey) && scope.downloadParam[scope.downloadKey].length === 0) {
                            ybWidget.ShowMessage("请选择需要导出的数据行", MESG_TYPE.Warn);
                            return;
                        }
                        formTemplate[0].firstChild.submit();
                    }
                }
            };
        }])

        .directive("ybWordCount", ['$parse', '$compile', function ($parse, $compile) {
            return {
                restrict: "A",
                require: "?ngModel",
                scope: {
                    maxSize: "="
                },
                link: function (scope, element, attrs, ctrl) {
                    var ngModelCtrl = ctrl;
                    if (!ngModelCtrl) {
                        return;
                    }
                    if (!scope.maxSize) {
                        return;
                    }
                    var showReminder = angular.isDefined(attrs.showReminder) ? scope.$eval(attrs.showReminder) : true;
                    var template = "<div style='color:#bbb; font-size:12px; line-height: 14px; height: 14px; margin-top: 10px;'>还可以输入{{surplusSize}}字</div>";
                    var wordcountTemplate = angular.element(template);
                    scope.surplusSize = scope.maxSize;
                    $compile(wordcountTemplate)(scope);
                    element.after(wordcountTemplate);

                    ngModelCtrl.$parsers.push(function (value) {
                        if (angular.isUndefined(value) || value.length <= 0) {
                            scope.surplusSize = scope.maxSize;
                            return value;
                        }
                        return countCurrentString(value);

                    });
                    ngModelCtrl.$formatters.unshift(function (value) {
                        var target = value;
                        if (!!value && value.length > 0 && scope.surplusSize == scope.maxSize) {
                            target = countCurrentString(value);
                        }
                        return target;
                    });

                    function countCurrentString(value) {
                        var currentCount = 0;
                        var target = value;
                        for (var i = 0, length = value.length; i < length; i++) {
                            if (value.charCodeAt(i) > 255) {
                                currentCount += 2;
                            } else {
                                currentCount += 1;
                            }
                            if (currentCount > scope.maxSize * 2) {
                                target = value.substring(0, i);
                                ngModelCtrl.$setViewValue(target);
                                ngModelCtrl.$render();
                                break;
                            }
                        }
                        scope.surplusSize = Math.floor((scope.maxSize * 2 - currentCount) / 2);
                        if (scope.surplusSize < 0) {
                            scope.surplusSize = 0;
                        }
                        return target;
                    }

                    if (showReminder) {
                        wordcountTemplate.css("display", "block");
                    } else {
                        wordcountTemplate.css("display", "none");
                    }
                }
            }
        }])

        .directive('ybEnter', ['$window', function ($window) {
            return {
                restrict: 'A',
                replace: true,
                link: function (scope, element, attrs) {
                    element.bind('keydown keypress', function (evt) {
                        var e = evt || $window.event;
                        if ((e.keyCode || e.which) == 13) {
                            scope.$apply(function () {
                                scope.$eval(attrs.ybEnter, {'event': e});
                            });
                            if (e.preventDefault()) {
                                e.preventDefault()
                            } else {
                                e.returnValue = false;
                            }
                        }
                    });
                }
            }
        }])

        .directive("ybFocus", function () {
            return {
                restrict: "A",
                require: 'ngModel',
                link: function (scope, element, attrs, ctrl) {
                    ctrl.focused = false;
                    element.bind('focus', function (evt) {
                        scope.$apply(function () {
                            ctrl.focused = true;
                        });
                    }).bind('blur', function () {
                        scope.$apply(function () {
                            ctrl.focused = false;
                        });
                    });
                }
            };
        })

        // 其他
        /**
         * 无权限则阻止点击事件，弹出提示
         * @example:
         *      yb-permission-check="ActionCode.SupplyList"
         *      yb-permission-check="[ActionCode.SupplyList, ActionCode.SupplyBind]"
         */
        .directive("ybPermissionCheck", ['UserContextService', 'ybWidget', '$parse', function (UserContextService, ybWidget, $parse) {
            return {
                restrict: "A",
                transclude: true,
                template: "<div ng-transclude ng-click='_checkPermission($event)'></div>",
                link: function (scope, element, attrs) {
                    var _permissionArr = [].concat($parse(attrs.ybPermissionCheck)(window));
                    scope._checkPermission = function (e) {
                        if (!UserContextService.CheckPermission(_permissionArr)) {
                            ybWidget.ShowToaster("error", "提示", "无权限操作");
                            e.stopPropagation();
                        }
                    }
                }
            }
        }])

        .directive("ybBtnPermission", ["$animate", "UserContextService", "$timeout", function ($animate, UserContextService, $timeout) {
            return {
                link: function (scope, element, attrs) {
                    var trigger = scope.$eval(attrs.ybBtnPermission);
                    $timeout(function () {
                        $animate[!(!trigger || !UserContextService.CheckPermission([trigger])) ? 'removeClass' : 'addClass'](element, 'ng-hide');
                    });
                }
            };
        }])

        .directive('ybFormClear', ["$timeout", function () {
            return {
                restrict: 'A',
                replace: true,
                scope: {
                    dataModel: '=?ngModel',
                    tipsName: "@",
                    formRequire: "=", // 原来的formRequire为: "@"，此处修改是为了取父作用域的变量，使该参数变得可配
                    selectObj: "&",
                    clearForm: "&",
                    inputDisabled: '=',
                    hideClear: '='
                },
                templateUrl: 'js/directive/tpl/formClear.html',
                link: function (scope) {
                    scope.tipName = '请选择' + scope.tipsName;
                    scope.tipNameClear = '清空' + scope.tipsName;
                }
            }
        }])
    ;
})(window, window.angular);